package util;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import models.CNAverage;
import models.SensorConfig;
import play.Logger;
import play.jobs.Every;
import play.jobs.Job;
import play.jobs.On;
import ch.bfh.abch.rems.REMSMulticastController;
import ch.bfh.abch.rems.sender.tinkerforge.TFMulticastSender;
import ch.bfh.abcm.rems.gateway.GateWayMessageType;
import ch.bfh.abcm.rems.gateway.GatewayMessage;
import ch.bfh.abcm.rems.sensors.tinkerforge.TFSensorType;

@Every("25s")
public class PeriodicNotificationJob extends Job {

    private static final String UNKNOWN = "unbekannt";
    private static final long NOTIF_INTERVAL_MS = 60 * 1000;
    private static final String NEW_LINE = "\r\n";

    private TFMulticastSender sender = new REMSMulticastController().getMulticastSender();
    
    @Override
    public void doJob() throws Exception {
        List<PeriodicNotifictionMessageElement> messageElements = createMessageElements();
        String message = formatMessge(messageElements);
        sendMulticastMessage(message);
    }

    private void sendMulticastMessage(String message) {
        GatewayMessage gatewayMessage = new GatewayMessage(GateWayMessageType.PERIODIC_NOTIFICATION, message, null);
        Logger.info("Send Periodic Notification: %s", gatewayMessage.getMessage());
        sender.sendGateWayMessage(gatewayMessage);
    }

    private String formatMessge(List<PeriodicNotifictionMessageElement> messageElements) {
        String message = "";
        for (PeriodicNotifictionMessageElement periodicNotifictionMessageElement : messageElements) {
            message += periodicNotifictionMessageElement.getElementText();
            message += NEW_LINE;
        }
        return message;
    }

    private List<PeriodicNotifictionMessageElement> createMessageElements() {
        List<PeriodicNotifictionMessageElement> messageElements = new ArrayList<PeriodicNotifictionMessageElement>();
        List<TFSensorType> sensorTypes = SensorConfig.getConfiguredSensorTypeList();
        for (TFSensorType sensorType : sensorTypes) {
            String value = getNotifIntervalAverage(sensorType);
            messageElements.add(new PeriodicNotifictionMessageElement(sensorType, value));
        }
        return messageElements;
    }

    private String getNotifIntervalAverage(TFSensorType sensorType) {
        long now = new Date().getTime();
        long startNotifIntervallTimeStamp = now - NOTIF_INTERVAL_MS;
        List<CNAverage> averages = CNAverage.getCNAsince(startNotifIntervallTimeStamp,sensorType);
        if (averages.size() <= 1) {
            Logger.warn("Not enough values: %s , returning %S", averages.size(), UNKNOWN);
            return UNKNOWN;
        }
        Logger.debug("Calculate Notification Average for Type: %s on %s values", sensorType, averages.size());
        try {
            float sum = 0;
            for (CNAverage cnAverage : averages) {
                sum += cnAverage.getNodeValue();
            }
            return String.valueOf(sum / averages.size());
        } catch (Exception e) {
            Logger.error(e, "Calculate Notification Average failed, returning %s", UNKNOWN);
            return UNKNOWN;
        }
    }

    private class PeriodicNotifictionMessageElement {
        private TFSensorType sensorType;
        private String value;

        public PeriodicNotifictionMessageElement(TFSensorType sensorType, String value) {
            super();
            this.sensorType = sensorType;
            this.value = value;
        }

        private String getElementText() {
            return sensorType + ": " + value + " " + sensorType.getUnit();
        }

        @Override
        public String toString() {
            return getElementText();
        }

    }

}
